package cn.jdy.framework.util;

import java.awt.Image;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

import javax.imageio.ImageIO;

import cn.jdy.framework.exception.BaseException;
import cn.jdy.framework.log.BaseLog;

/***
 * 文件读写工具类 
 * */
public class FileUtil {
     
    public static void main(String[] args) {
        String sourcePath = "D:\\cache\\dtree.js";
        String tempPath = System.getProperty("java.io.tmpdir");// 临时文件路径
        String tmpFile = tempPath+"temp.js";
        System.out.println(tmpFile);
        // 合并文件，输出到零时目录
        JsCssUtil.compress(new File(sourcePath), new File(tmpFile));
        // 将零时目录文件 覆盖替换源文件
        fileCopy(new File(tmpFile), new File(sourcePath));
    }
    
    // TODO 文件下载
    /**
     * 读取文件返回一个字符串
     * */
    public static String readFile(File file) {
        StringBuffer sb = new StringBuffer();
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(file);
            byte[] b = new byte[1024];
            int len = -1 ;
            while ((len=fis.read(b)) != -1) {
                sb.append(new String(b, 0, len));
            }
        } catch (Exception e) {
            BaseLog.e(FileUtil.class,"FileRWUtil.readFile", e);
        }finally{
            try {
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return sb.toString().trim();
    }

    /**
     * 将字符串写入文件
     * */
    public static void writeFile(String path, String str) {
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(path);
            fos.write(str.getBytes());
        } catch (Exception e) {
            BaseLog.e(FileUtil.class,"FileRWUtil.writeFile", e);
        }finally{
            try {
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    /**
     * 将文件内容按行读取到List中
     * */
    public static List<String> readFileByLine(File file){
        List<String> sqlDataList = null;
        try {
            // 将文件内容逐行读取到sqlDataList中
           BufferedReader br = new BufferedReader(new FileReader(file));
           String temp = null;
           sqlDataList = new ArrayList<String>();
            while((temp = br.readLine())!=null){
                if(!"".equals(temp.trim())){// 忽略空行
                    sqlDataList.add(temp);
                }
            }
            br.close();
        } catch (Exception e) {
            BaseLog.e(FileUtil.class,"", e);
        }
        return sqlDataList;
    }
    
    /**
     * 将文件内容按行读取到List中
     * */
    public static void writeFileByLine(File file,List<String> ListStr){
        try {
            // 将文件内容逐行读取到sqlDataList中
           BufferedWriter bw = new BufferedWriter(new FileWriter(file));
           for (String str : ListStr) {
               bw.write(str);
           }
           bw.close();
        } catch (Exception e) {
            BaseLog.e(FileUtil.class,"writeFileByLine", e);
        }
    }
    
    /**
     * @description:把源目录下的所有文件复制到目标目录下
     * @param srcDir 源目录
     * @param dstDir ：目标目录
     */
    public static void dirCopy(String srcDir, String dstDir) {
        if (!StringUtil.stringIsEmpty(srcDir) && !StringUtil.stringIsEmpty(dstDir)) {
            File file = new File(srcDir);
            String name = null;// 待上传文件名
            if (file.isDirectory()) {// 如果为目录，则按目录传
                File[] files = file.listFiles();
                File dstFile = null;
                for (File f : files) {
                    if (f.isFile()) {
                    name = dstDir + "/" + f.getName();
                    dstFile = new File(name);
                    fileCopy(f, dstFile);
                    }
                }
            }
        }
    }
    
    /**
     * @description: 文件复制
     * @param src
     * @param dst ：
     */
    public static void fileCopy(File src, File dst) {
        try {
            if (dst.isFile()) {
                dst.deleteOnExit();
                dst = new File(dst.getAbsolutePath());
            }
            // 如果所在文件目录不存在，则先创建所须目录，再操作文件
            String parentFileName = dst.getParent();
            if (!(new File(parentFileName)).exists()) {
                (new File(parentFileName)).mkdirs();
            }
            FileInputStream fis = new FileInputStream(src);
            FileOutputStream fos = new FileOutputStream(dst);
            byte[] b = new byte[1024];
            int len = -1;
            while ((len = fis.read(b)) != -1) {
                fos.write(b, 0, len);
            }
            fis.close();
            fos.close();
        } catch (Exception e) {
            e.printStackTrace();
            throw new BaseException("文件复制异常");
        }
    }
    
    /**
     * @description: 根据文件名获取文件的后缀
     * @param fileName
     * @return：
     */
    public static String getExtention(String fileName) {
        int pos = fileName.lastIndexOf(".");
        return fileName.substring(pos);
    }
    
    /**
     * 文件压缩gzip
     * **/
    public static void gzip(String file, String zipFile) {
        try {
            // 打开需压缩文件作为文件输入流
            FileInputStream fin = new FileInputStream(file);
            // 建立压缩文件输出流
            FileOutputStream fout = new FileOutputStream(zipFile);
            // 建立gzip压缩输出流
            GZIPOutputStream gzout = new GZIPOutputStream(fout);
            byte[] buf = new byte[1024];// 设定读入缓冲区尺寸
            int num;
            
            while ((num = fin.read(buf)) != -1) {
                gzout.write(buf, 0, num);
            }
            gzout.close();// !!!关闭流,必须关闭所有输入输出流.保证输入输出完整和释放系统资源.
            fout.close();
            fin.close();
        } catch (IOException e) {
            System.out.println(e);
        }
    }
    
    /**
     * 文件解压unGzip
     * **/
    public static void unGzip(String zipFile, String file) {
        try {
            // 建立gzip压缩文件输入流
            FileInputStream fin = new FileInputStream(zipFile);
            // 建立gzip解压工作流
            GZIPInputStream gzin = new GZIPInputStream(fin);
            // 建立解压文件输出流
            FileOutputStream fout = new FileOutputStream(file);
            byte[] buf = new byte[1024];
            int num;
            
            while ((num = gzin.read(buf, 0, buf.length)) != -1) {
                fout.write(buf, 0, num);
            }
            gzin.close();
            fout.close();
            fin.close();
        } catch (IOException e) {
            System.out.println(e);
        }
    }
    
    /**
     * 将文件转换成字符串
     * **/
    public static String file2str(File file){
        byte[] bytes = null;
        try {
            FileInputStream fis = new FileInputStream(file);
            bytes = new byte[fis.available()];
            fis.read(bytes);
            fis.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        if(bytes==null){
            return null;
        }else{
            // 将二进制转为字符串
            return StringUtil.byte2hex( bytes );
        }
    }
    
    /**
     * 将字符串转为文件
     * **/
    public static void str2file(String str,String pathout){
        try {
            byte[] fileByte = StringUtil.hex2byte(str);//字符串转二进制
            InputStream in = new ByteArrayInputStream(fileByte);
            byte[] b = new byte[1024];
            int nRead = 0;
            
            OutputStream o = new FileOutputStream(pathout);
            while( ( nRead = in.read(b) ) != -1 ){
                o.write( b, 0, nRead );
            }
            o.flush();
            o.close();
            in.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 等比压缩图像
     * @param src 源图像文件
     * @param target压缩后要存放的目标文件
     * @param maxWidth压缩后允许的最大宽度
     * @param maxHeight 压缩后允许的最大高度
     * @throws java.io.IOException
     */
    public static void transform(String src, String target, int maxWidth, int maxHeight) throws Exception {
        String dirStr = target.substring(0, target.lastIndexOf("/") + 1);
        File dir = new File(dirStr);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        File srcFile = new File(src);
        File targetFile = new File(target);
        AffineTransform transform = new AffineTransform();
        BufferedImage biSrc = ImageIO.read(srcFile);
        int width = biSrc.getWidth();
        int height = biSrc.getHeight();
        int newWidth = maxWidth;
        int newHeight = (int) (((double) newWidth / width) * height);
        if (newHeight > maxHeight) {
            newHeight = maxHeight;
            newWidth = (int) (((double) newHeight / height) * width);
        }
        double scaleX = (double) newWidth / width;
        double scaleY = (double) newHeight / height;
        transform.setToScale(scaleX, scaleY);
        AffineTransformOp ato = new AffineTransformOp(transform, null);
        BufferedImage biTarget = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_3BYTE_BGR);
        biTarget.getGraphics().drawImage( biSrc.getScaledInstance(newWidth, newHeight, Image.SCALE_SMOOTH), 0, 0, null);
        ato.filter(biSrc, biTarget);
        ImageIO.write(biTarget, "jpeg", targetFile);
    }
    
    /**
     * 按规则生成文件路径
     * BASE_PATH/ + 文件存放路径 + 年月日/ + 文件名称 + 文件后缀(suffix)
     * */  
    public static String getFilePath(String basePath,String suffix){
        StringBuilder path = new StringBuilder(basePath);
        path.append("/");
        path.append(DateUtil.getCurrentDate3());
        path.append("/");
        path.append(IDUtil.getID());
        path.append(suffix);
        return path.toString() ;
    }
}
